package system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import common.config.exception.CustomException;
import common.config.jwt.JwtUtil;
import common.config.jwt.TokenInfo;
import common.model.dto.ActivateEmailToken;
import common.model.dto.ModifyEmailToken;
import common.model.enums.EmailNotifyTypeEnum;
import common.model.enums.EmailValidEnum;
import common.model.enums.UserDeletedEnum;
import common.model.po.SysUser;
import common.model.request.ActivateEmailRequest;
import common.model.request.ModifyEmailRequest;
import common.model.request.SendEmailRequest;
import common.model.response.base.Result;
import common.service.RedissonCacheService;
import common.util.EmailTemplateUtil;
import common.util.UserChecker;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import system.model.request.SendActivateEmailRequest;
import system.service.MailService;
import system.service.SysUserService;
import system.service.UserEmailService;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Objects;

/**
 * 描述
 *
 * @author 米泽鹏
 * @since 2023-11-7 下午 9:09
 */
@Slf4j
@Service
public class UserEmailServiceImpl implements UserEmailService {

	@Resource
	private RedissonCacheService redissonCacheService;
	@Resource
	private SysUserService userService;
	@Resource
	private MailService mailService;
	@Value("${satisfactory.domain}")
	private String domain;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Result<?> activateEmail(ActivateEmailRequest request) {
		// 先校验token
		ActivateEmailToken activateEmailToken;
		try {
			activateEmailToken = JwtUtil.parseActivateEmailToken(request.getToken());
		} catch (SignatureException | MalformedJwtException | ExpiredJwtException | UnsupportedJwtException | IllegalArgumentException e) {
			throw new CustomException("链接已失效");
		}
		if (activateEmailToken == null) {
			throw new CustomException("链接已失效");
		}
		Long userId = activateEmailToken.getUserId();
		if (userId == null) {
			throw new CustomException("用户信息无效");
		}
		String tokenInCache = redissonCacheService.getActivateEmailTokenStringByUserId(userId);
		if (tokenInCache == null) {
			throw new CustomException("链接已失效");
		}
		if (!tokenInCache.equals(request.getToken())) {
			throw new CustomException("链接已失效");
		}
		// 校验用户信息
		SysUser user = userService.lambdaQuery().eq(SysUser::getId, userId).eq(SysUser::getIsDeleted, UserDeletedEnum.NOT_DELETED.getValue()).one();
		UserChecker.checkUser(user);
		String newEmail = activateEmailToken.getNewEmail();
		String oldEmail = activateEmailToken.getOldEmail();
		// 激活邮箱
		if (Objects.equals(user.getEmail(), newEmail)) {
			user.setEmailValid(EmailValidEnum.VALID.getValue());
			user.updateById();
			// 旧邮箱解绑通知
			if (StrUtil.isNotBlank(oldEmail) && CollUtil.contains(user.getEmailNotifyTypes(), EmailNotifyTypeEnum.EMAIL_UNBOUND.getValue()) && EmailValidEnum.VALID.getValue().equals(user.getEmailValid())) {
				SendEmailRequest sendEmailRequest = new SendEmailRequest();
				sendEmailRequest.setToList(Collections.singletonList(oldEmail));
				sendEmailRequest.setSubject(EmailNotifyTypeEnum.EMAIL_UNBOUND.getDesc() + "【幸福工厂游戏工具网站】");
				sendEmailRequest.setText(EmailTemplateUtil.getEmailUnboundContent(domain, user.getUsername(), user.getNickname()));
				sendEmailRequest.setHtml(true);
				mailService.sendEmail(sendEmailRequest);
			}
			redissonCacheService.removeActivateEmailTokenString(userId).throwExceptionIfFailed();
		} else {
			redissonCacheService.removeActivateEmailTokenString(userId).throwExceptionIfFailed();
			throw new CustomException("邮箱已变更，此链接已失效，请重新发送激活邮件");
		}
		// 新邮箱激活通知
		SendEmailRequest sendEmailRequestForNewEmail = new SendEmailRequest();
		sendEmailRequestForNewEmail.setToList(Collections.singletonList(newEmail));
		sendEmailRequestForNewEmail.setSubject("邮箱已激活【幸福工厂游戏工具网站】");
		sendEmailRequestForNewEmail.setText(EmailTemplateUtil.getActivateSuccessContent(domain, user.getUsername(), user.getNickname()));
		sendEmailRequestForNewEmail.setHtml(true);
		mailService.sendEmail(sendEmailRequestForNewEmail);
		return Result.success();
	}

	@Override
	public Result<?> modifyEmail(ModifyEmailRequest request) {
		// 先校验token
		ModifyEmailToken modifyEmailToken;
		try {
			modifyEmailToken = JwtUtil.parseModifyEmailToken(request.getToken());
		} catch (SignatureException | MalformedJwtException | ExpiredJwtException | UnsupportedJwtException | IllegalArgumentException e) {
			throw new CustomException("链接已失效");
		}
		if (modifyEmailToken == null) {
			throw new CustomException("链接已失效");
		}
		Long userId = modifyEmailToken.getUserId();
		if (userId == null) {
			throw new CustomException("用户信息无效");
		}
		String tokenInCache = redissonCacheService.getModifyEmailTokenStringByUserId(userId);
		if (tokenInCache == null) {
			throw new CustomException("链接已失效");
		}
		if (!tokenInCache.equals(request.getToken())) {
			throw new CustomException("链接已失效");
		}
		// 校验用户信息
		SysUser user = userService.lambdaQuery().eq(SysUser::getId, userId).eq(SysUser::getIsDeleted, UserDeletedEnum.NOT_DELETED.getValue()).one();
		UserChecker.checkUser(user);
		String newEmail = modifyEmailToken.getNewEmail();
		String oldEmail = modifyEmailToken.getOldEmail();
		// 校验邮箱是否已变更
		if (Objects.equals(user.getEmail(), newEmail)) {
			// 向新邮箱发送激活邮件
			sendEmail(userId, newEmail, oldEmail, user.getUsername(), user.getNickname());
			redissonCacheService.removeModifyEmailTokenString(userId).throwExceptionIfFailed();
		} else {
			redissonCacheService.removeModifyEmailTokenString(userId).throwExceptionIfFailed();
			throw new CustomException("邮箱已变更，此链接已失效，请重新发送激活邮件");
		}
		return Result.success();
	}

	@Override
	public Result<?> sendMailBoxActivationEmail(SendActivateEmailRequest request) {
		Long userId = request.getUserId();
		String email = request.getEmail();
		SysUser user = userService.lambdaQuery().eq(SysUser::getId, userId).eq(SysUser::getIsDeleted, UserDeletedEnum.NOT_DELETED.getValue()).one();
		UserChecker.checkUser(user);
		if (EmailValidEnum.VALID.getValue().equals(user.getEmailValid())) {
			throw new CustomException("您的邮箱已激活，无需再次激活");
		}
		sendEmail(userId, email, null, user.getUsername(), user.getNickname());
		return Result.success();
	}

	private void sendEmail(Long userId, String newEmail, String oldEmail, String username, String nickname) {
		// 生成新邮箱激活的token
		ActivateEmailToken activateEmailToken = new ActivateEmailToken();
		activateEmailToken.setUserId(userId);
		activateEmailToken.setNewEmail(newEmail);
		activateEmailToken.setOldEmail(oldEmail);
		TokenInfo tokenInfo = JwtUtil.createActivateEmailToken(activateEmailToken);
		redissonCacheService.cacheActivateEmailTokenString(userId, tokenInfo.getToken(), tokenInfo.getExpireDate()).throwExceptionIfFailed();
		// 向新邮箱发送激活邮件
		SendEmailRequest sendEmailRequest = new SendEmailRequest();
		sendEmailRequest.setToList(Collections.singletonList(newEmail));
		sendEmailRequest.setSubject("激活邮箱【幸福工厂游戏工具网站】");
		sendEmailRequest.setText(EmailTemplateUtil.getActivateMailBoxContent(domain, tokenInfo.getToken(), username, nickname));
		sendEmailRequest.setHtml(true);
		mailService.sendEmail(sendEmailRequest);
	}

}
